package top.truism.stack;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

/**
 * 猫狗队列
 * addCat  -- Cat元素出队
 * addDog  -- Dog元素入队
 * poll    -- 从队列中找最早入队的元素出队
 * pollCat -- 按Cat元素入队顺序出队
 * pollDog -- 按Dog元素入队顺序出队
 * pollAll -- 按元素入队顺序出队
 */
public class CatDogQueue {

    private Queue<PetQueue> catQueue;

    private Queue<PetQueue> dogQueue;

    private int count;

    public CatDogQueue() {
        this.catQueue = new ArrayDeque<>();
        this.dogQueue = new ArrayDeque<>();
        this.count = 0;
    }

    public void  addCat(Cat cat) {
        catQueue.add(new PetQueue(cat, ++count));
    }

    public void addDog(Dog dog) {
        dogQueue.add(new PetQueue(dog, ++count));
    }

    public Cat pollCat() {
        return (Cat) catQueue.poll().getPet();
    }

    public Dog pollDog() {
        return (Dog) dogQueue.poll().getPet();
    }

    public Pet poll() {
        PetQueue cat = catQueue.peek();
        PetQueue dog = dogQueue.peek();
        if(cat.getCount() > dog.getCount()) {
            return dogQueue.poll().pet;
        }else {
            return catQueue.poll().pet;
        }
    }

    public boolean isCatQueueEmpty() {
        return catQueue.isEmpty();
    }

    public boolean isDogQueueEmpty() {
        return dogQueue.isEmpty();
    }

    public boolean isEmpty() {
        return isCatQueueEmpty() && isDogQueueEmpty();
    }

    public List<Pet> pollAll() {
        List<Pet> list = new ArrayList<>();
        while (!isEmpty()) {
            if(isCatQueueEmpty()) {
                list.add(dogQueue.poll().pet);
            }else if(isDogQueueEmpty()) {
                list.add(catQueue.poll().pet);
            }else {
                PetQueue cat = catQueue.peek();
                PetQueue dog = dogQueue.peek();
                if(cat.getCount() > dog.getCount()) {
                    list.add(dogQueue.poll().pet);
                }else {
                    list.add(catQueue.poll().pet);
                }
            }
        }
        return list;
    }

    class PetQueue {

        private Pet pet;

        private int count;

        public PetQueue(Pet pet, int count) {
            this.pet = pet;
            this.count = count;
        }

        public String getType() {
            return this.pet.getType();
        }

        public int getCount() {
            return this.count;
        }

        public Pet getPet() {
            return pet;
        }
    }

    static abstract class Pet {

        protected abstract String getType();

    }

    static class Cat extends Pet {
        protected String getType() {
            return "Cat";
        }
    }

    static class Dog extends Pet {
        protected String getType() {
            return "Dog";
        }
    }


}


